﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;

namespace SimpleReactiveObjects.Test
{
    [TestClass]
    public class ReactiveVariableTest
    {
        [TestMethod]
        public void CreateTest()
        {
            var v1 = new ReactiveVariable<int>();

            v1.Value.Is(0);

            var v2 = new ReactiveVariable<double>(5.0);
            v2.Value.Is(5.0);
        }

        [TestMethod]
        public void SetValueTest()
        {
            var v = new ReactiveVariable<int>(1);

            v.Value.Is(1);

            v.Value = 2;

            v.Value.Is(2);
        }

        [TestMethod]
        public void SubscribeTest()
        {
            var v = new ReactiveVariable<int>();

            int? y = null;
            var yc = 0;
            v.Subscribe(x =>
            {
                y = x;
                yc++;
            });

            y.Is(0);
            yc.Is(1);

            int? z = null;
            var zc = 0;
            v.Value = 10;
            v.Subscribe(x =>
            {
                z = x;
                zc++;
            });

            y.Is(10);
            z.Is(10);
            yc.Is(2);
            zc.Is(1);

            v.Value = 10;

            y.Is(10);
            z.Is(10);
            yc.Is(2);
            zc.Is(1);
        }

        [TestMethod]
        public void DisposeTest()
        {
            var v = new ReactiveVariable<int>();
            v.Value.Is(0);

            int? y = null;
            var yc = 0;
            var ycmp = false;
            v.Subscribe(x =>
            {
                y = x;
                yc++;
            },
            () => ycmp = true
            );

            v.Value = 1;
            v.Value.Is(1);

            AssertEx.DoesNotThrow(() =>
            {
                v.Dispose();
            });

            AssertEx.Throws<ObjectDisposedException>(() =>
            {
                v.Value = 10;
            });

            AssertEx.Throws<ObjectDisposedException>(() =>
            {
                v.Value.Is(1);
            });

            AssertEx.Throws<ObjectDisposedException>(() =>
            {
                v.Subscribe(x => { });
            });

            y.Is(1);
            yc.Is(2);
            ycmp.IsFalse();
        }
    }
}
